/********************************************************************************
 *@description: 数据字典
 *@author: Xhd
 *@API: 清泉
 *@date: 2024-04-23 09:18:00
 *@version: V1.0.0
**********************************************************************************/

import React, { Component, useRef } from 'react';
import { Modal, Cascader, List, Form, Input, Button, Space } from 'antd';
import { DndProvider, useDrag, useDrop } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import TheTable from '@/components/TheTable';
import TheButton from '@/components/TheButton';
import update from 'immutability-helper';
import { apiDictionaryTree, apiDictionaryAdd, apiDictionaryEdit, apiDictionaryDelete, apiDictionaryReorder } from "@/request/dictionary";
import _ from "lodash";
import "../style/index.less";

const type = 'DraggableBodyRow';
const DraggableBodyRow = ({ index, moveRow, className, style, ...restProps }) => {
  const ref = useRef(null);
  const [{ isOver, dropClassName }, drop] = useDrop({
    accept: type,
    collect: (monitor) => {
      const { index: dragIndex } = monitor.getItem() || {};
      if (dragIndex === index) {
        return {};
      }
      return {
        isOver: monitor.isOver(),
        dropClassName: dragIndex < index ? ' drop-over-downward' : ' drop-over-upward',
      };
    },
    drop: (item) => {
      moveRow(item.index, index);
    },
  });
  const [, drag] = useDrag({
    type,
    item: {
      index,
    },
    collect: (monitor) => ({
      isDragging: monitor.isDragging(),
    }),
  });
  drop(drag(ref));
  return (
    <tr
      ref={ref}
      className={`${className}${isOver ? dropClassName : ''}`}
      style={{
        cursor: 'move',
        ...style,
      }}
      {...restProps}
    />
  );
};
class Dictionary extends Component {
  constructor(props) {
    super(props)
    this.queryFormRef = React.createRef();
    this.state = {
      columns: [
        {
          title: '排序',
          dataIndex: 'sort',
          key: 'sort'
        },
        {
          title: '属性名称',
          dataIndex: 'name',
          key: 'name'
        },
        {
          title: '属性值',
          dataIndex: 'value',
          key: 'value',
          render: (text) => {
            return text ? text : '-'
          }
        },
        {
          title: '备注',
          dataIndex: 'remark',
          key: 'remark',
          render: (text) => {
            return text ? text : '-'
          }
        },
        {
          title: '操作',
          dataIndex: 'operate',
          key: 'operate',
          render: (text, record) => {
            if (this.state.dataSource.length > 1) {
              return <div>
                <TheButton haspermi={['setting:dictionary:edit']} onClick={() => this.editDictionary(record)} >编辑</TheButton>
                {!record.value && <TheButton haspermi={['setting:dictionary:deleted']} onClick={() => this.delDictionary(record)} >删除</TheButton>}
              </div>
            } else {
              return <div>
                <TheButton haspermi={['setting:dictionary:edit']} onClick={() => this.editDictionary(record)} >编辑</TheButton>
              </div>
            }
          }
        },
      ],
      dataSource: [],
      option: [],
      fristLevel: [],
      LevelCache: '',
      visible: false,
      title: '',
      pid: '',
      initialValues: {},
      delVisible: false,
      delData: '',
      highlightData: ['', ''],
      isAdd: true
    }
  }

  componentDidMount() {
    this.getData()
  }
  // 获取数据
  getData = async (values) => {
    await apiDictionaryTree().then(res => {
      if (res.code === 0) {
        let data = JSON.parse(JSON.stringify(res.data))
        let option = data.map(v => {
          v.label = v.name
          v.value = v.dictionaryId
          v.children.map(k => {
            k.label = k.name
            k.value = k.dictionaryId
            return k
          })
          return v
        })
        let dataSource = res.data[0].children ? res.data[0].children : []
        let isAdd = false
        let sec = dataSource.map(element => {
          return element.value
        });
        if (sec.filter(Boolean).length > 0) {
          isAdd = true
        }
        if (!values) {
          this.setState({
            isAdd,
            option,
            fristLevel: res.data,
            dataSource: res.data[0].children ? res.data[0].children : []
          })
        } else {
          this.setState({
            option,
            fristLevel: res.data,
          }, () => {
            let list = _.compact(res.data.map(v => {
              if (v.dictionaryId === values.dictionaryId) {
                return v
              }
            }))
            this.secondData(list[0])
          })
        }
      }
    })
  }
  // 名称选择
  onChange = (value, selectedOptions) => {
    const { fristLevel } = this.state
    let data = _.compact(fristLevel.map(v => {
      if (value && v.dictionaryId === value[0]) {
        return v
      }
    }))
    let dataSource = data[0] ? data[0].children : fristLevel[0].children
    let isAdd = false
    let sec = dataSource.map(element => {
      return element.value
    });
    if (sec.filter(Boolean).length > 0) {
      isAdd = true
    }
    this.setState({
      isAdd,
      dataSource,
      LevelCache: data[0],
      highlightData: value ? value : ['', '']
    })
  }
  // 一级字典点击事件
  secondData = (value) => {
    let dataSource = value.children
    let isAdd = false
    let sec = dataSource.map(element => {
      return element.value
    });
    if (sec.filter(Boolean).length > 0) {
      isAdd = true
    }
    this.setState({
      isAdd,
      dataSource,
      LevelCache: value,
      highlightData: [value.dictionaryId, '']
    })
  }
  // 新增按钮
  addDictionary = (pid) => {
    this.setState({
      visible: true,
      title: "新增",
      pid,
      initialValues: {}
    })
  }
  // 编辑
  editDictionary = (record) => {
    this.setState({
      visible: true,
      title: "编辑",
      initialValues: record
    })
  }
  // 新增、编辑提交
  onFinish = async (values) => {
    const { title, pid, initialValues, LevelCache } = this.state
    if (title === "新增") {
      await apiDictionaryAdd({ ...values, pid }).then(res => {
        if (res.code === 0) {
          React.$message({
            type: 'success',
            content: '新增成功'
          })
        }
      })
    } else {
      await apiDictionaryEdit({ ...values, dictionaryId: initialValues.dictionaryId }).then(res => {
        if (res.code === 0) {
          React.$message({
            type: 'success',
            content: '编辑成功'
          })
        }
      })
    }
    this.setState({
      visible: false
    }, () => {
      this.getData(LevelCache)
    })
  }
  // 删除
  delDictionary = (value) => {
    this.setState({
      delVisible: true,
      delData: value
    })
  }
  // 确认删除
  onDeleted = async () => {
    const { delData, LevelCache } = this.state
    await apiDictionaryDelete({ dictionaryId: delData.dictionaryId }).then(res => {
      if (res.code === 0) {
        React.$message({
          type: 'success',
          content: '删除成功'
        })
        this.setState({
          delVisible: false
        }, () => {
          this.getData(LevelCache)
        })
      }
    })
  }
  // 高亮显示
  getRowClassName = (record, index) => {
    const { highlightData } = this.state
    if (typeof record !== 'object') return
    return highlightData[1] === record.dictionaryId ? "highlight" : ''
  }
  // 表格拖拽
  moveRow = () => (dragIndex, hoverIndex) => {
    const { dataSource, LevelCache } = this.state
    const dragRow = dataSource[dragIndex];
    let newData = update(dataSource, {
      $splice: [
        [dragIndex, 1],
        [hoverIndex, 0, dragRow],
      ],
    })
    this.setState({
      dataSource: newData,
    }, async () => {
      let dictionaryIdList = this.state.dataSource.map(v => {
        return v.dictionaryId
      })
      await apiDictionaryReorder({ dictionaryIdList }).then(res => {
        if (res.code === 0) {
          this.getData(LevelCache)
        }
      })
    });
  }
  // 表格行点击高亮
  tableClick = (record, index) => {
    const { highlightData } = this.state
    let newHighlight = [highlightData[0], record.dictionaryId]
    this.setState({
      highlightData: newHighlight
    })
  }

  render() {
    const { columns, dataSource, option, fristLevel, title, visible, initialValues, delVisible, highlightData, isAdd } = this.state;
    const filter = (inputValue, path) => path.some((option) => option.label.toLowerCase().indexOf(inputValue.toLowerCase()) > -1);
    return (<div className='p-layout-box'>
      <p>
        名称：<Cascader options={option}
          onChange={(value, selectedOptions) => this.onChange(value, selectedOptions)}
          showSearch={{ filter, }} changeOnSelect
        />
      </p>
      <div style={{ display: 'flex', marginTop: '20px' }}>
        <div style={{ width: '30%', textAlign: 'center' }}>
          <List header="字典导航"
            bordered
            dataSource={fristLevel}
            renderItem={(item) => <List.Item className={highlightData[0] === item.dictionaryId ? 'highlight' : ''} style={{ textAlign: 'center' }} onClick={() => { this.secondData(item) }}>{item.name}</List.Item>} />
        </div>
        <div style={{ width: '68%', marginLeft: '2%' }}>
          <div style={{ textAlign: 'right', marginBottom: '10px' }}>
            {!isAdd &&
              <TheButton haspermi={['setting:dictionary:add']} type="primary" size="middle" onClick={() => this.addDictionary(dataSource[0].pid)} >+&nbsp;新增</TheButton>}
          </div>
          <DndProvider backend={HTML5Backend}>
            <TheTable scroll={{ x: 'max-content', y: '63vh' }}
              columns={columns}
              dataSource={dataSource}
              rowClassName={this.getRowClassName}
              components={{
                body: {
                  row: DraggableBodyRow,
                },
              }}
              onRow={(_, index) => {
                const attr = {
                  index,
                  moveRow: this.moveRow(_, index),
                  onClick: () => this.tableClick(_, index)
                };
                return attr;
              }}
            />
          </DndProvider>
        </div>
      </div>
      <Modal
        title={title}
        footer={null}
        open={visible}
        onCancel={() => this.setState({ visible: false })}
        destroyOnClose={true}
      >
        <Form ref={ref => this.formRef = ref} initialValues={title === '新增' ? {} : initialValues} onFinish={(values) => this.onFinish(values)}
          labelAlign="right" labelCol={{ span: 4, offset: 2 }}
        >
          <Form.Item label="属性名称" name='name' rules={[{ required: true }]}  >
            <Input placeholder='请输入2~50字名称' minLength={2} maxLength={50} />
          </Form.Item>
          {initialValues.value &&
            <Form.Item label="属性值" name='value' rules={[{ required: true }]}  >
              <Input />
            </Form.Item>
          }
          <Form.Item label="备注" name='remark' >
            <Input.TextArea placeholder='请输入备注（0~100字）' maxLength={100} />
          </Form.Item>
          <Form.Item style={{ textAlign: 'right' }}>
            <Space>
              <Button onClick={() => this.setState({ visible: false })} >取消</Button>
              <Button type='primary' htmlType="submit" >确定</Button>
            </Space>
          </Form.Item>
        </Form>
      </Modal>
      <Modal
        title="删除提醒"
        open={delVisible}
        onCancel={() => this.setState({ delVisible: false })}
        onOk={() => this.onDeleted()}
      >
        确认删除吗？
      </Modal>
    </div>)
  }
}

export default Dictionary